﻿using System;
using System.ComponentModel;
using System.IO;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
using Seagull.Generic;
using System.Linq;

namespace Seagull.Configuration
{
    public class PathConfig
    {
        private int _realtimePort;

        [XmlAttribute("实时数据本地网络端口号")]
        [DisplayName("实时数据本地网络端口号")]
        [Category("实时数据")]
        public int RealTimePort
        {
            get { return _realtimePort; }
            set
            {
                if(!Config.SupressValidation)
                {
                    if(value < 1024 || value > 65535)
                    {
                        throw new ArgumentOutOfRangeException("value",
                            string.Format("端口号{0}无效。", value));
                    }
                }
                _realtimePort = value;
            }
        }

        #region Configable Path

        private string _rawDataPath;

        [XmlAttribute("原始数据存放路径")]
        [DisplayName("原始数据存放路径")]
        [Category("文件路径")]
        public string RawDataPath
        {
            get { return _rawDataPath; }
            set { _rawDataPath = GenericHelper.NormalizeFolderPath(value); }
        }

        private string _compressTempPath;

        [XmlAttribute("数据压缩暂存路径")]
        [DisplayName("数据压缩暂存路径")]
        [Category("文件路径")]
        public string CompressTempPath
        {
            get { return _compressTempPath; }
            set { _compressTempPath = GenericHelper.NormalizeFolderPath(value); }
        }

        private string _backupPathOnRemovableDrive;

        [XmlAttribute("移动硬盘数据备份路径")]
        [DisplayName("移动硬盘数据备份路径")]
        [Description("数据备份到移动硬盘后的存放路径，请勿指定盘符。例如：\"GpuHMI\\Backup\"")]
        [Category("文件路径")]
        public string BackupPathOnRemovableDrive
        {
            get { return _backupPathOnRemovableDrive; }
            set
            {
                if(!Config.SupressValidation)
                {
                    if(Path.IsPathRooted(value))
                    {
                        throw new ArgumentException("移动硬盘数据备份路径: 请勿指定盘符！", "value");
                    }
                }
                _backupPathOnRemovableDrive = GenericHelper.NormalizeFolderPath(value);
            }
        }

        private string _statPath;

        [XmlAttribute("统计文件存放路径")]
        [DisplayName("统计文件存放路径")]
        [Category("文件路径")]
        public string StatPath
        {
            get { return _statPath; }
            set { _statPath = GenericHelper.NormalizeFolderPath(value); }
        }

        private string _channelStatPath;

        [XmlAttribute("统计文件2存放路径")]
        [DisplayName("统计文件2存放路径")]
        [Category("文件路径")]
        public string ChannelStatPath
        {
            get { return _channelStatPath; }
            set { _channelStatPath = GenericHelper.NormalizeFolderPath(value); }
        }

        private string _dcuIpAddress;

        [XmlAttribute("数据集中单元地址")]
        [DisplayName("数据集中单元地址")]
        [Category("文件路径")]
        public string DcuIpAddress
        {
            get { return _dcuIpAddress; }
            set
            {
                if(!Config.SupressValidation)
                {
                    var ipRegex = new Regex(
                        @"\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b");
                    var match = ipRegex.Match(value);
                    if(!match.Success || match.Length != value.Length)
                    {
                        throw new ArgumentException("数据集中单元地址: 不合法的IP地址。", "value");
                    }
                }
                _dcuIpAddress = value;
            }
        }

        #endregion

        public const string ParsedDataFolderName = "Data";
        public const string UnparsedDataFolderName = "Log";

        #region Readonly generated config

        [XmlIgnore]
        [Browsable(false)]
        public string SourceDataFolder
        {
            get
            {
                return GenericHelper.CombineAndNormilizePath(
                    RawDataPath, ParsedDataFolderName, DcuIpAddress);
            }
        }

        [XmlIgnore]
        [Browsable(false)]
        public string SourceLogFolder
        {
            get
            {
                return GenericHelper.CombineAndNormilizePath(
                    RawDataPath, UnparsedDataFolderName, DcuIpAddress);
            }
        }

        [XmlIgnore]
        [Browsable(false)]
        public string CompressDataFolder
        {
            get
            {
                return GenericHelper.CombineAndNormilizePath(
                    CompressTempPath, ParsedDataFolderName, DcuIpAddress);
            }
        }

        [XmlIgnore]
        [Browsable(false)]
        public string CompressLogFolder
        {
            get
            {
                return GenericHelper.CombineAndNormilizePath(
                    CompressTempPath, UnparsedDataFolderName, DcuIpAddress);
            }
        }

        [XmlIgnore]
        [Browsable(false)]
        public string DataFolderOnRemovableDevice
        {
            get
            {
                return GenericHelper.CombineAndNormilizePath(
                    BackupPathOnRemovableDrive, ParsedDataFolderName, DcuIpAddress);
            }
        }

        [XmlIgnore]
        [Browsable(false)]
        public string LogFolderOnRemovableDevice
        {
            get
            {
                return GenericHelper.CombineAndNormilizePath(
                    BackupPathOnRemovableDrive, UnparsedDataFolderName, DcuIpAddress);
            }
        }

        [XmlIgnore]
        [Browsable(false)]
        public string StatFolder
        {
            get { return Path.Combine(StatPath, DcuIpAddress); }
        }

        [XmlIgnore]
        [Browsable(false)]
        public string ChannelStatFolder
        {
            get { return Path.Combine(ChannelStatPath, DcuIpAddress); }
        }

        #endregion


        #region Editable in file config

        [XmlAttribute("统计文件扩展名")]
        [Browsable(false)]
        public string StatFileExtension { get; set; }

        [XmlAttribute("数据文件扩展名")]
        [Browsable(false)]
        public string DataFileExtension { get; set; }

        [XmlAttribute("压缩文件扩展名")]
        [Browsable(false)]
        public string CompressedFileExtension { get; set; }

        #endregion

        [XmlAttribute("移动硬盘上允许的目录名称")]
        [DisplayName("移动硬盘上允许的目录名称")]
        [Category("其他")]
        public string AllowedFolderNamesOnRemovableDevice { get; set; }

        [XmlAttribute("报警记录文件")]
        [DisplayName("报警记录文件")]
        [Category("其他")]
        public string AlertFileName { get; set; }

        [XmlAttribute("短信发送失败记录文件")]
        [DisplayName("短信发送失败记录文件")]
        [Category("其他")]
        public string FailedSmsAlertFile { get; set; }

        private string _localDriveLetters;

        [XmlAttribute("本地硬盘盘符列表")]
        [DisplayName("本地硬盘盘符列表")]
        [Category("其他")]
        public string LocalDriveLetters
        {
            get { return _localDriveLetters; }
            set
            {
                if(!Config.SupressValidation)
                {
                    if(!value.All(char.IsLetter))
                    {
                        throw new ArgumentOutOfRangeException("value");
                    }
                }
                _localDriveLetters = value;
            }
        }
    }
}